#region Copyright (c) 2003-2004 ComponentGo!
/*
*********************************************************************
*                                                                   *
*       ComponentGo! Component Library                              *
*                                                                   *
*       Copyright (c) 2003-2004 ComponentGo!                        *
*       ALL RIGHTS RESERVED                                         *
*                                                                   *
*********************************************************************
*/
#endregion

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace ComponentGo.Calendars {

	/// <summary>
	/// Contains various static methods used in many calendar controls.
	/// </summary>
	public sealed class CalendarTools {
		
		private CalendarTools() {}

		internal static void FillRectangle(Graphics g, Rectangle rt, Color color1, Color color2, bool vertical) {
			if (color1==color2) {
				using (Brush brush = new SolidBrush(color1))
					g.FillRectangle(brush, rt);
			}
			else {
				using (Brush brush = new LinearGradientBrush(rt, color1, color2, 
					vertical ? LinearGradientMode.Vertical : LinearGradientMode.Horizontal))
					g.FillRectangle(brush, rt);
			}
		}

		/// <summary>
		/// Calculates a number of minutes corresponding to a unit of time (cell) displayed 
		/// in a calendar.
		/// </summary>
		/// <param name="hres">Determines the time resolution of a calendar.</param>
		/// <returns>Number of minutes per unit (cell).</returns>
		public static TimeSpan CalcMinsResolution(HoursResolutions hres) {
			switch (hres) {
				case HoursResolutions.OneDay:			return new TimeSpan(1, 0, 0, 0); 
				case HoursResolutions.Twelve:			return new TimeSpan(12, 0, 0); 
				case HoursResolutions.One:				return new TimeSpan(1, 0, 0);
				case HoursResolutions.Half:				return new TimeSpan(0, 30, 0);
				case HoursResolutions.Quart:			return new TimeSpan(0, 15, 0);
				case HoursResolutions.TenMinutes:		return new TimeSpan(0, 10, 0);
				case HoursResolutions.SixMinutes:		return new TimeSpan(0, 6, 0);
				case HoursResolutions.FiveMinutes:		return new TimeSpan(0, 5, 0);
				case HoursResolutions.Minute:			return new TimeSpan(0, 1, 0);
				case HoursResolutions.QuarterMinute:	return new TimeSpan(0, 0, 15);
				case HoursResolutions.Second:			return new TimeSpan(0, 0, 1);
			}
			throw new InvalidOperationException();
		}

		internal static bool AMPM {
			get {
				string h = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern;
				return h.IndexOf("tt")>=0;
			}
		}

		internal static TimeSpan Mul(TimeSpan ts, int v) {
			return new TimeSpan(ts.Ticks*v);
		}

		internal static TimeSpan Div(TimeSpan ts, int v) {
			return new TimeSpan(ts.Ticks/v);
		}

		internal static double Div(TimeSpan ts1, TimeSpan ts2) {
			return ts1.TotalSeconds/ts2.TotalSeconds;
		}

		static int dark(int c) {
			return c-c/10;
		}

		internal static Color Dark(Color c) {
			return Color.FromArgb(dark(c.R), dark(c.G), dark(c.B));
		}

		internal static void SetAlignment(StringFormat sf, ContentAlignment ca) {
			switch (ca) {
				case ContentAlignment.BottomCenter:
				case ContentAlignment.BottomLeft:
				case ContentAlignment.BottomRight:
					sf.LineAlignment = StringAlignment.Far;
					break;
				case ContentAlignment.MiddleCenter:
				case ContentAlignment.MiddleLeft:
				case ContentAlignment.MiddleRight:
					sf.LineAlignment = StringAlignment.Center;
					break;
				case ContentAlignment.TopCenter:
				case ContentAlignment.TopLeft:
				case ContentAlignment.TopRight:
					sf.LineAlignment = StringAlignment.Near;
					break;
			}
			switch (ca) {
				case ContentAlignment.BottomLeft:
				case ContentAlignment.MiddleLeft:
				case ContentAlignment.TopLeft:
					sf.Alignment = StringAlignment.Near;
					break;
				case ContentAlignment.BottomCenter:
				case ContentAlignment.MiddleCenter:
				case ContentAlignment.TopCenter:
					sf.Alignment = StringAlignment.Center;
					break;
				case ContentAlignment.BottomRight:
				case ContentAlignment.MiddleRight:
				case ContentAlignment.TopRight:
					sf.Alignment = StringAlignment.Far;
					break;
			}
		}

		internal static DateTime GetMondayDate(DateTime dt) {
			if (dt.DayOfWeek==DayOfWeek.Sunday)
				return dt.AddDays(-6);
			return dt.Date.AddDays(-(dt.DayOfWeek-DayOfWeek.Monday));
		}

		internal static DateTime GetSundayDate(DateTime dt) {
			return dt.Date.AddDays(-(dt.DayOfWeek-DayOfWeek.Sunday));
		}

		public static void PaintClock(Graphics g, DateTime time, int x, int y, int size) {
			PaintClock(g, time, new Rectangle(x, y, size, size));
		}

		const float sin30 = 0.5f;
		const float cos30 = 0.8660254f;

		internal static void PaintClock(Graphics g, DateTime time, Rectangle rect) {
			Color color1, color2;
			if (time.Hour>=12) {
				color1 = SystemColors.WindowText;
				color2 = SystemColors.Window;
			}
			else {
				color1 = SystemColors.Window;
				color2 = SystemColors.WindowText;
			}
			using (SolidBrush brush = new SolidBrush(color1))
			using (Pen pen = new Pen(color2))
			using (Pen pen2 = new Pen(SystemColors.WindowText)) {
				float r = rect.Height/2.0f;
				float r2 = r-r/4.5f;
				float x = rect.X+rect.Width/2.0f;
				float y = rect.Y+rect.Height/2.0f;

				float sinr = sin30*r, sinr2 = sin30*r2;
				float cosr = cos30*r, cosr2 = cos30*r2;

				g.FillPie(brush, rect, 0, 360);

				g.DrawLine(pen, x, y-r, x, y-r2);
				g.DrawLine(pen, x, y+r, x, y+r2);
				g.DrawLine(pen, x-r, y, x-r2, y);
				g.DrawLine(pen, x+r, y, x+r2, y);
				g.DrawLine(pen, x-sinr, y+cosr, x-sinr2, y+cosr2);
				g.DrawLine(pen, x-sinr, y-cosr, x-sinr2, y-cosr2);
				g.DrawLine(pen, x+sinr, y+cosr, x+sinr2, y+cosr2);
				g.DrawLine(pen, x+sinr, y-cosr, x+sinr2, y-cosr2);
				g.DrawLine(pen, x-cosr, y+sinr, x-cosr2, y+sinr2);
				g.DrawLine(pen, x-cosr, y-sinr, x-cosr2, y-sinr2);
				g.DrawLine(pen, x+cosr, y+sinr, x+cosr2, y+sinr2);
				g.DrawLine(pen, x+cosr, y-sinr, x+cosr2, y-sinr2);

				g.DrawArc(pen2, rect, 0, 360);

				double m = 2*Math.PI*time.Minute/60;
				g.DrawLine(pen, x, y, x+(float)Math.Sin(m)*r, y-(float)Math.Cos(m)*r);

				double h = 2*Math.PI*(60*time.Hour+time.Minute)/(12*60);
				g.DrawLine(pen, x, y, x+(float)Math.Sin(h)*r/2, y-(float)Math.Cos(h)*r/2);
			}
		}
	}

}
